home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS02.ADF / C / shell.c < prev    next >
C/C++ Source or Header  |  1989-05-30  |  10KB  |  373 lines

  1. /* CLI shell program 11/85 REJ */
  2. /* This program has been put into the public domain by
  3.    Lunge Software.  Feel free to modify this, but please
  4.    do not remove the credits.
  5.    If you have any suggestions for improvement, please
  6.    either send me mail.
  7.  
  8.       Written By:  Randell E Jesup
  9.                    Lunge Software
  10.                    2340 15th St
  11.                    Troy, NY     12180
  12.  
  13.    To use this program, create a 'command file' named
  14. 'commands' in the sys: directory.  This file should consist
  15. of lines with the following format:
  16.  
  17. nnnnnn       yyyy;zzzzz;xxxxx;...
  18.  
  19. 'nnnnnn' is a string that you type from the cli (like 'ls').
  20. 'yyyy',etc, are the commands to be executed when the program
  21.     sees 'nnnnnn'.  Multiple commands are seperated by ';'.
  22.  
  23.    Example:
  24. ls       list
  25. dl       delete
  26. cp       copy
  27. dlram    cd ram:;delete #?;cd df0:
  28.  
  29. Whatever you typed after the command will concatenated to
  30. the end of the final command.  You may also type multiple
  31. commands directly from the keyboard (i.e. 'list x;type y'.)
  32.  
  33. There is one other thing cpp does.  If you give it a line in
  34. the command file like this:
  35.  
  36. prd      type %1 to %2; delete %1
  37.  
  38. it will replace %n with the nth argument you entered from
  39. the keyboard.  All arguments after the highest used by %n
  40. will be appended to the end of the last command line.
  41.  
  42. example: 'prd test prt:' -> 'type test to prt:; delete test'
  43.  
  44. I have a number of plans for enhancements to this, so get
  45. word to me soon with any ideas you might have.  This code
  46. may not be the prettiest, but it works.
  47. A problem in 1.0 caused me to have to simulate the 'cd'
  48. command.  As soon as I get 1.1, I will update this (if it
  49. was fixed.)
  50.  
  51.    There are certain things that don't work exactly as they
  52. do under cli (yet).  Ctrl-C won't be passed through, and if
  53. you use 'xxx ?' it won't work, and any program that wants
  54. input from the current window won't work.  To solve this,
  55. redirect input to '*' or a 'con' window.
  56.  
  57. Good luck, and have fun!
  58. */
  59.  
  60. #include "stdio.h"
  61. #include "libraries/dos.h"
  62.  
  63. extern char *strrchr(),*stpblk(),*strchr();
  64.  
  65. char curr_dir[100];
  66. char tmpbuf[256];
  67.  
  68. int old_lock,new_lock;
  69.  
  70. struct CMD {
  71.    struct CMD *Next_CMD;
  72.    char   *string;
  73.    char   *replace;
  74. } *CMD_List[16], *End[16], temp;
  75.  
  76. char buff[256];
  77. char buff2[256];
  78.  
  79. FILE *cf;
  80.  
  81. int input_file,output_file;
  82.  
  83. extern char *malloc();
  84.  
  85. long *
  86. alloc(lth)
  87. register unsigned lth;
  88. {
  89.    register char *ptr;
  90.  
  91.    if(!(ptr = malloc(lth)))
  92.    {  printf("Not enough memory for getting %d bytes", lth);
  93.       exit(20);
  94.    }
  95.    return((long *) ptr);
  96. }
  97.  
  98. /*
  99.  * This is a pain!  I have to handle cd as a special case!
  100.  */
  101. void exec_cmd(p)
  102.    char *p;
  103. {
  104.       char *q;
  105.  
  106.       if ((*p == 'c') && (*(p+1) == 'd') && ((*(p+2) == ' ')
  107.           || (*(p+2) == '\0')))
  108.       {  q = p + 1;
  109.          while (*++q == ' ') ;     /* skip blanks */
  110.          if (*q == '\0')
  111.          {  printf(curr_dir);
  112.             printf("\n");
  113.          } else {
  114.             while (*q == '/')
  115.             {  register char *t;
  116.  
  117.                q++;
  118.                t = strrchr(curr_dir,'/');
  119.                if (t == NULL)
  120.                {  t = strchr(curr_dir,':');
  121.                   if (t++ == NULL)
  122.                   {  printf("Bad Dir Name!");
  123.                      break;
  124.                   }
  125.                }
  126.                *t = '\0';
  127.             }
  128.             if ((*q != ' ') && (*q != '\0'))
  129.             {  if (strchr(q,':') != NULL)
  130.                   if (*q == ':')
  131.                   {  *(strchr(curr_dir,':')) = '\0';
  132.                      strcat(curr_dir,q);
  133.                   } else strcpy(curr_dir,q);
  134.                else {
  135.                   if (curr_dir[strlen(curr_dir)-1] != ':')
  136.                      strcat(curr_dir,"/");
  137.                   strcat(curr_dir,q);
  138.                }
  139.             }
  140.             new_lock = Lock(curr_dir,SHARED_LOCK);
  141.             if (new_lock != NULL)
  142.             {  old_lock = CurrentDir(new_lock);
  143.                UnLock(old_lock);
  144.             } else printf("Directory %s does not exist\n",q);
  145.          }
  146.       } else Execute(p,0,output_file);
  147. }
  148.  
  149. void command_loop()
  150. /* command arrays are initialized */
  151. /* now loop, replacing commands, until "stop" is seen */
  152. {
  153. /* current dir is set to df0:, as there is no way to find
  154.  * out what the current dir is.
  155.  * If you pass a 'cd xxx' command to dos, it'll execute it,
  156.  * but neither the program's or the cli's dir will be
  157.  * changed.  This means it must be simulated.  Also, if you
  158.  * type this from dos:
  159.  * 'cd devs:', 'cd :', 'cd', it will say you are in the
  160.  * 'devs:' directory, but in reality you are in df0:
  161.  * (assuming the disk is in df0:).  This works correctly
  162.  * here.
  163.  */
  164.    strcpy(curr_dir,"df0:");
  165.    new_lock = Lock(curr_dir,SHARED_LOCK);
  166.    old_lock = CurrentDir(new_lock);
  167.    UnLock(old_lock);
  168.    for(;;)
  169.    {  int total;
  170.       struct CMD *ptr;
  171.       int i;
  172.       register char *p,*q,*s,*t;
  173.  
  174.       printf("cpp> ");
  175.       total = 0;
  176.       fgets(tmpbuf,256,stdin);  /* get an input line */
  177.       s = p = tmpbuf;
  178.       while ((*p != '\n') && (*p != '\0'))
  179.          p++;
  180.       *p = '\0';                /* strip newline */
  181.       if (tmpbuf[0] == '\0') continue;
  182.       if (!strcmp(tmpbuf,"stop")) break;
  183.       while (*s != NULL)
  184.       {  q = strchr(s,';'); /* break multiple input cmds  */
  185.          if (q == NULL)     /* copy 1 at a time into buff */
  186.          {  strcpy(buff,s);
  187.             *s = NULL;
  188.          } else {
  189.             t = buff;
  190.             while (s < q)
  191.                *t++ = *s++; /* copy first command into buff */
  192.             s++;
  193.             *t = '\0';
  194.          }
  195.          sscanf(buff,"%s",temp.string);
  196.          for (i=0;i<strlen(temp.string);i++)
  197.             total += temp.string[i];
  198.          total &= 15;
  199.          ptr = CMD_List[total];
  200. /*
  201.  * search through the list for the command
  202.  */
  203.          while (ptr != NULL)
  204.          {  if (!strcmp(ptr->string,temp.string))
  205.             {  char *u;
  206.                struct { char *x;} args[10];
  207.                int n;
  208.                int m = -1;
  209. /* got a match for replace */
  210.                strcpy(buff2,ptr->replace);
  211.                u = buff2;
  212. /* break out args, then replace '%n's */
  213.                break_buff(&buff[strlen(ptr->string)],args);
  214.                while ((u = strchr(u,'%')) != NULL)
  215.                {  n = *(u+1) - '0' - 1;
  216.                   insstr(u,args[n].x,args[n+1].x);
  217.                   if (n > m)
  218.                      m = n;
  219.                }
  220.                strcat(buff2," ");
  221.                strcat(buff2,args[m+1].x);
  222.                break;
  223.             }
  224.             ptr = ptr->Next_CMD;
  225.          }
  226. /* now, execute the command */
  227.          if (ptr == NULL)     /* was replacement done ?  */
  228.             p = buff;
  229.          else
  230.             p = buff2;
  231. /*       printf("total cmd: %s\n",p);     */
  232.          for (;p != NULL;)
  233.          {  q = strchr(p,';'); /* each command may expand */
  234.             if (q != NULL)     /* to multiple commands    */
  235.                *q++ = '\0';
  236. /*          printf("cmd: %s\n",p);        */
  237.             exec_cmd(p);
  238.             p = q;
  239.          }   
  240.       }
  241.    }
  242. }
  243.  
  244. main(argc, argv)
  245.    int argc;
  246.    char *argv[];
  247. {
  248.    char *FileName;
  249.    char NullFile[30];
  250.    register int i;
  251.  
  252.    NullFile[0] = '\0';
  253.    temp.Next_CMD = NULL;
  254.    for (i=0;i<16;i++)
  255.    {
  256.       CMD_List[i] = NULL;
  257.       End[i] = NULL;
  258.    }
  259.    if (argc < 2)
  260.       FileName = "sys:commands\0";
  261.    else {
  262.       argv++;
  263.       if ((*argv)[0] == '?')
  264.       {
  265.          printf("command_file/K: ");
  266.          FileName = NullFile;
  267.          scanf("%s",FileName);
  268.       }
  269.       else FileName = argv[0];
  270.    }
  271.    printf("Filename: ");
  272.    printf(FileName);
  273.    printf("\n");
  274.    cf = fopen(FileName,"r");
  275.    if (cf == NULL)
  276.    {  printf("Command file not found!\n");
  277.       return(10);
  278.    }
  279. /*
  280.  * right now, abbreviations can be no more than 30 chars
  281.  */
  282.    temp.string = (char *) alloc(31);
  283.    temp.replace = (char *) alloc(226);
  284.    while (fgets(buff,255,cf) != NULL)
  285.    {
  286.       register int total = 0;
  287.       register char *p = buff;
  288.       register char *s = temp.replace;
  289.       
  290.       while ((*p != '\n') && (*p != '\0'))
  291.          p++;
  292.       *p = '\0';                  /* drop newline char   */
  293.       sscanf(buff,"%s",temp.string);
  294.       p = &buff[strlen(temp.string)+2];
  295.       while (*p == ' ')           /* drop leading spaces */
  296.          p++;
  297.       strcpy(s,p);                /* copy p to s */
  298.       for (i=0;i<strlen(temp.string);i++)
  299.          total += temp.string[i]; /* calculate hash index */
  300.       total &= 15;
  301. /*
  302.  * insert abbreviation into 1 of 16 linked lists.  This is
  303.  * done to reduce search time, and may not be needed.
  304.  */
  305.       if (CMD_List[total] == NULL)
  306.       {  CMD_List[total] = (struct CMD *)
  307.                                   alloc(sizeof(struct CMD));
  308.          End[total] = CMD_List[total];
  309.          *CMD_List[total] = temp;
  310.       } else {
  311.          End[total]->Next_CMD = (struct CMD *)
  312.                                   alloc(sizeof(struct CMD));
  313.          End[total] = End[total]->Next_CMD;
  314.          *End[total] = temp;
  315.       }
  316.       End[total]->string = (char *)
  317.                                  alloc(strlen(temp.string));
  318.       strcpy(End[total]->string,temp.string);
  319.       End[total]->replace = (char *)
  320.                                 alloc(strlen(temp.replace));
  321.       strcpy(End[total]->replace,temp.replace);
  322.    }
  323. /* get input and output files */
  324.    input_file = Input();
  325.    output_file = Output();
  326.    printf("Command Pre-Processor v1.00\n");
  327.    printf(" courtesy Lunge Software Development\n");
  328.    buff[0] = '\0';
  329.    buff2[0] = '\0';
  330.    command_loop();
  331.    printf("Command Pre-Processing terminated\n");
  332. }
  333.  
  334. break_buff(src,args)   /* parse arguments */
  335.    char *src;
  336.    struct { char *x;} args[];
  337. {
  338.    int i = 0;
  339.  
  340.    src = stpblk(src);         /* skip leading blanks */
  341.    args[0].x = src;
  342.    while (*src != '\0')       /* delims = \0 and space */
  343.    {  if (*src == ' ')
  344.       {  args[++i].x = ++src;
  345.          src = stpblk(src);
  346.       } else
  347.          ++src;
  348.    }
  349.    for (i++;i<10;i++)         /* all others are null */
  350.       args[i].x = src;
  351. /* for (i=0;i<10;i++)
  352.       printf("arg[%d] = %s\n",i,args[i].x);  */
  353. }
  354.  
  355. insstr(dest,src,end)
  356. /*
  357.  * insert a string at a given position.  string starts at
  358.  * src and goes to end-1
  359.  */
  360.    char *dest,*src,*end;
  361. {
  362.    char tmp[256];
  363.  
  364.    strcpy(tmp,&dest[2]);
  365. /*   printf("start=%d, end=%d, remainder=%s, replace=%s\n",
  366.            src,end,tmp,src);           */
  367.    while (src != end)
  368.       *dest++ = *src++;
  369.    strcpy(dest,tmp);
  370. }
  371.  
  372. /* ------------- eof -------------- */
  373.